/************************************
*  Copyright (C) 2010 Julien MOTTIN.
*  Contact: julien.mottin@gueydan.eu
*
*  This file is part of Gueydan.
*
*  Gueydan is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Gueydan is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Gueydan.  If not, see <http://www.gnu.org/licenses/>.
*
*************************************/
#ifndef REPOSITORY_H
#define REPOSITORY_H

// QtCore
#include <QString>
#include <QList>
#include <QMap>
#include <QStringList>

// Local
#include "beerxmlhandler.h"

class Hop;

enum OpenStatus
{
    Closed = 0,
    ReadOnly,
    ReadWrite
};

class Repository
{
public:

    // Standard ctor
    Repository(const QString &iDir);
    ~Repository();

    /*
    * Close the repository : close all file handles,
    * flush all lists, commit all changes
    */
    void Close();

    /*
    * Open the repository in the specified mode :
    * read or read/write mode
    */
    void OpenRead();
    void OpenWrite();

    /*
    * Adds a hop in the repository. The Repository
    * must have been opened in write mode
    *
    * params
    *   [in] iHop : the Hop instance to add
    * returns
    *   0  : success
    *   1  : invalid open mode (!=ReadWrite)
    *   2  : unexpected error
    *   -1 : invalid argument 
    */
    int AddHop(Hop *ipHop);

    /*
    * Search for a Hop definition from its name.
    * If no such Hop found, then NULL is returned
    * This const method won't commit any change applied
    * to the returned Hop pointer
    *
    * params
    *   [in] iHopName : the name of the hop to search
    *   [out] oHop : the result of the search
    * returns
    *   NULL : hop instance not found
    *   else the addref'ed searched instance
    */
    Hop * SearchHop(const QString &iHopName) const;

    /*
    * Return all the hops contained in the repository
    *
    * returns
    *   the list of name
    */
    QStringList ListHopNames() const;

    /*
    * Adds a fermentable in the repository. The Repository
    * must have been opened in write mode
    *
    * params
    *   [in] ipFerm : the Fermentable instance to add
    * returns
    *   0  : success
    *   1  : invalid open mode (!=ReadWrite)
    *   2  : unexpected error
    *   -1 : invalid argument
    */
    int AddFerm(Fermentable *ipFerm);

    /*
    * Search for a Fermentable definition from its name.
    * If no such Fermentable found, then NULL is returned
    * This const method won't commit any change applied
    * to the returned Fermentable pointer
    *
    * params
    *   [in] iFermName : the name of the hop to search
    *   [out] oHop : the result of the search
    * returns
    *   NULL : ferm instance not found
    *   else the addref'ed searched instance
    */
    Fermentable * SearchFerm(const QString &iFermName) const;

    /*
    * Return all the fermentable contained in the repository
    *
    * returns
    *   the list of names
    */
    QStringList ListFermNames() const;

    int AddMisc(Misc *ipMisc);
    Misc * SearchMisc(const QString &iMiscName) const;
    QStringList ListMiscNames() const;

    int AddYeast(Yeast *ipYeast);
    Yeast * SearchYeast(const QString &iYeastName) const;
    QStringList ListYeastNames() const;

private:

    // Forbidden
    Repository(const Repository &);
    Repository & operator=(const Repository &);

    // internal set struct
    struct BeerXMLSet
    {
        QMap<QString,BeerXMLHandler> _Map;
        bool _HasChanged;
    };

    // Generic beerxml services
    int AddObject(BeerXMLObject *ipObject, BeerXMLSet *ipSet);
    const BeerXMLHandler SearchObject(const QString &iObjName,const BeerXMLSet *ipSet) const;
    QStringList ListObjNames(const BeerXMLSet *ipSet) const;
    void OpenSet(const QString &iDirName, BeerXMLSet *ipSet);
    void CommitSet(const QString &iDirName, BeerXMLSet *ipSet);

    // Internal Data
    QString     _Directory;
    OpenStatus  _Status;

    // Sets
    BeerXMLSet _Hops;
    BeerXMLSet _Ferms;
    BeerXMLSet _Miscs;
    BeerXMLSet _Yeasts;
};

#endif // REPOSITORY_H
